package com.jiayou.server

import com.jiayou.codec.ChannelDecoder
import com.jiayou.exception.NotSafeException
import com.jiayou.handler.ServerChildHandler
import com.jiayou.handler.ServerIdleStateHandler
import com.jiayou.handler.ServerMessageChannelHandler
import com.jiayou.message.ChannelMessage
import com.sun.org.apache.xpath.internal.operations.Bool
import io.netty.bootstrap.ServerBootstrap
import io.netty.channel.*
import io.netty.channel.group.DefaultChannelGroup
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioServerSocketChannel
import io.netty.handler.logging.LogLevel
import io.netty.handler.logging.LoggingHandler
import io.netty.handler.timeout.IdleState
import io.netty.handler.timeout.IdleStateEvent
import io.netty.handler.timeout.IdleStateHandler
import io.netty.util.concurrent.GlobalEventExecutor
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import java.util.concurrent.TimeUnit

/**
@author 李 双
@data   2020-11-19  11:23
@info
 */

@Component
class ImServer(
    @Value("${'$'}{netty.port}") var port: Int,
    @Value("${'$'}{netty.boss}") var bossNum: Int,
    @Value("${'$'}{netty.work}") var workNum: Int,
    @Value("${'$'}{netty.safe}") var safeCheeck: Boolean
) {
    private lateinit var boss: NioEventLoopGroup         //接待Reactor线程池
    private lateinit var worker: NioEventLoopGroup       //读写线程池Reactor线程池
    private lateinit var serverBootstrap: ServerBootstrap //主服务

    @Autowired
    private lateinit var serverChildHandler: ServerChildHandler

    companion object {
        val log: Logger = LoggerFactory.getLogger(ImServer::class.java)
    }

    init {
        if (safeCheeck)
            if (bossNum > 100 || workNum > 100)
                throw NotSafeException("group number may be not safe!")
        log.info("Netty-Im bind port in ：${port}")
        log.info("Netty-Im bossgroup number is：${bossNum}")
        log.info("Netty-Im workgroup number is：${workNum}")
    }

    fun startServer() {

        if (bossNum == 0 || workNum == 0) {
            boss = NioEventLoopGroup()
            worker = NioEventLoopGroup()
        } else {
            boss = NioEventLoopGroup(bossNum)
            worker = NioEventLoopGroup(workNum)
        }

        serverBootstrap = ServerBootstrap()
        serverBootstrap.group(boss, worker)                         //设置两个线程组
            .channel(NioServerSocketChannel::class.java)            //使用NioServerSocketChannel作为服务通道的实现
            .option(ChannelOption.SO_BACKLOG, 128)            //设置线程队列连接个数
            .childOption(ChannelOption.SO_KEEPALIVE, true)    //设置保持活动的连接状态
            .handler(LoggingHandler(LogLevel.INFO))                  //加入日志处理handler
            .childHandler(serverChildHandler)

        val server = serverBootstrap.bind(port).sync()   //绑定端口并进行同步操作
        server.addListener {
            if (it.isSuccess)
                log.info("netty-im server have been bind in $port!")
            else
                log.error("netty-im server run error!")
        }
        server.channel().closeFuture().sync()

        boss.shutdownGracefully()
        worker.shutdownGracefully()
    }
}

